package hiresoft.network;

import java.io.InputStream;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;

/**
 * The net input stream for the network class.  Handles
 * all incoming packets.
 *
 * @see Packets
 * @author Filip Jaros
 */
public class NetInputStream extends BufferedInputStream
{
    /**
     * Constructor for NetInputStream.
     *
     *
     * @param in the {@link InputStream}
     */
    public NetInputStream(InputStream in)
    {
        super(in);
    }

    /**
     * Checks if a packet is available.
     * Used for {@link Network#Ready()}
     *
     * @return true if a packet is available
     * @throws IOException
     */
    public boolean packetAvailable() throws IOException
    {
        if (available() >= 6)
        {
            mark(6);
            if (read() == 0xFF)
            {
                read();
                int len = getDWord();
                reset();
                return (available() >= len);
            }
        }
        return false;
    }

    /**
     * Identifies the type of packet received
     * from the server.  Types of packets can
     * be viewed in the {@link Packets} class.
     *
     * @see Packets
     *
     * @return the ID of the packet
     * @throws IOException
     */
    public int getPacketId() throws IOException
    {
        if (read() == 0xFF)
        {
            int packetId = read();
            getDWord();
            return packetId;
        }
        return -1;
    }

    /**
     * Reads the next 4 bytes of data from
     * the input stream as an integer.
     *
     * @return the next 4 bytes of data
     * @throws IOException
     */
    public int getWord() throws IOException
    {
        return ((read() & 0x00FF) |
               ((read() << 8) & 0xFF00));
    }

    /**
     * Reads the next 8 bytes of data from
     * the input stream as an integer.
     *
     * @return the next 8 bytes of data
     * @throws IOException
     */
    public int getDWord() throws IOException
    {
        return (read() & 0x000000FF) |
               ((read() << 8) & 0x0000FF00) |
               ((read() << 16) & 0x00FF0000) |
               ((read() << 24) & 0xFF000000);
    }

    /**
     * Reads the next piece of data from the stream
     * as a string.  Input stream is read until a
     * terminator is found.
     *
     * @return the next String of data
     * @throws IOException
     */
    public String getString() throws IOException 
    {
        ByteArrayOutputStream b = new ByteArrayOutputStream();
        while (available() > 0)
        {
            int i = read();
            if (i != 0)
                b.write(i);
            else
                break;
        }
        return b.toString();
    }
}

